#include "net.h"
#include <sys/select.h>
#define MAX_SOCK_FD 1024

int main(int argc, char *argv[])
{
	int i, ret, fd, newfd;
	fd_set set, tmpset;
	Addr_in clientaddr;
	socklen_t clientlen = sizeof(Addr_in);
	/*检查参数，小于3个 直接退出进程*/
	Argment(argc, argv);
	/*创建已设置监听模式的套接字*/
	fd = CreateSocket(argv);

	FD_ZERO(&set);
	FD_ZERO(&tmpset);
	//将fd添加到集合中，索引值为fd的元素置为1
	FD_SET(fd, &set);
	while(1){
		tmpset = set;
		//select函数在返回时，会自动清除fd_set集合中所有未就绪的文件描述符。
		//这意味着，如果某个文件描述符在调用select时被认为是可监视的，
		//但在select函数等待期间没有变为就绪状态，则它在fd_set集合中对应的位将被清零。
		//这也是为啥要引入 tmpset
		if( (ret = select(MAX_SOCK_FD, &tmpset, NULL, NULL, NULL)) < 0)
			ErrExit("select");
		if(FD_ISSET(fd, &tmpset) ){
			/*接收客户端连接，并生成新的文件描述符*/
			if( (newfd = accept(fd, (Addr *)&clientaddr, &clientlen) ) < 0)
				perror("accept");
			printf("[%s:%d]已建立连接\n", 
					inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
			FD_SET(newfd, &set);
		}else{ //处理客户端数据
			for(i = fd + 1; i < MAX_SOCK_FD; i++){
				if(FD_ISSET(i, &tmpset)){
					if( DataHandle(i) <= 0){
						if( getpeername(i, (Addr *)&clientaddr, &clientlen) )
							perror("getpeername");
						printf("[%s:%d]断开连接\n", 
								inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
						FD_CLR(i, &set);
					}
				}
			}
		}
	}
	return 0;
}

